/*!
\copyright  Copyright (c) 2024 Qualcomm Technologies International, Ltd.
            All Rights Reserved.
            Qualcomm Technologies International, Ltd. Confidential and Proprietary.
\file
\brief      Implementation of Audio Curation application testing functions

*/

#ifdef INCLUDE_ANC_V3

#include "audio_curation_objective.h"
#include "audio_curation_intent.h"
#include "audio_curation_objective_message.h"
#include "audio_curation_objective_private.h"
#include "audio_curation_router.h"
#include "audio_curation.h"
#include "phy_state.h"
#include "context_framework.h"
#include "ui_inputs.h"
#include "ui.h"
#include "peer_ui.h"
#include "message.h"
#include "logging.h"
#include "anc_audio_curation.h"
#include "headset_test_audio_curation.h"
#include "audio_curation_objective_tuning.h"
#include "audio_curation_objective_transparency.h"
#include "audio_curation_monitor.h"
#include "audio_curation_hearingtest.h"
#include "audio_curation_usecase_manager.h"
#include "multidevice.h"
#include "peer_signalling.h"

/**************************************************************************
                    APIs FOR AUDIO CURATION
 **************************************************************************/

static ac_router_consumer_t get_MesageDirection(uint32_t channel)
{
    ac_router_consumer_t msg_dir = ac_router_consumer_local;
    multidevice_side_t device_side = Multidevice_GetSide();
    /* channel_0 means left, channel_1 means right */
    if(channel == 0)
    {
        msg_dir = device_side == multidevice_side_left ? ac_router_consumer_local : ac_router_consumer_remote;
    }
    else
    {
        msg_dir = device_side == multidevice_side_right ? ac_router_consumer_local : ac_router_consumer_remote;
    }

    DEBUG_LOG_ALWAYS("get_MesageDirection %x", msg_dir);

    return msg_dir;
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_SetAncEnable(void)
{
    appTestAudioCuration_SetAncEnable();
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_SetAncDisable(void)
{
    appTestAudioCuration_SetAncDisable();
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_SetMode(uint8 req_mode)
{
    appTestAudioCuration_SetMode(req_mode);
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_EnterTuning(uint8 mode)
{
    appTestAudioCuration_EnterTuning(mode);
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_WriteFilter(void)
{
    DEBUG_LOG("HeadsetTestAudioCuration_WriteFilter");
    ac_router_event_data_t uiInputData;

    uiInputData.msgLen = 0;
    uiInputData.consumerFlag = ac_router_consumer_local_remote;
    uiInputData.delay = PEER_ANC_UI_INPUT_DELAY_MS;
    uiInputData.msg = NULL;

    AudioCurationRouter_SendEvent(ui_input_anc_enter_tuning_mode, &uiInputData);
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_ExitTuning(void)
{
    appTestAudioCuration_ExitTuning();
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_SetToggleConfig(uint8 toggle_index, uint8 mode)
{
    DEBUG_LOG("HeadsetTestAudioCuration_SetToggleConfig : index : %d, mode : %d ", toggle_index , mode);
    ac_router_event_data_t uiInputData;

    MESSAGE_MAKE(msg, ac_obj_msg_set_toggle_cfg_t);
    msg->toggle_index = toggle_index;
    msg->req_obj =  mode;

    uiInputData.msgLen       = sizeof(ac_obj_msg_set_toggle_cfg_t);
    uiInputData.consumerFlag = ac_router_consumer_local_remote;
    uiInputData.delay        = PEER_ANC_UI_INPUT_DELAY_MS;
    uiInputData.msg          = msg;

    AudioCurationRouter_SendEvent(ui_input_audio_curation_set_toggle_config, &uiInputData);
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_ToggleAnc(void)
{
    if (appPhyStateIsOutOfCase())
    {
        DEBUG_LOG("HeadsetTestAudioCuration_ToggleOnOff");
        ac_router_event_data_t uiInputData;

        uiInputData.msgLen       = 0;
        uiInputData.consumerFlag = ac_router_consumer_local_remote;
        uiInputData.delay        = PEER_ANC_UI_INPUT_DELAY_MS;
        uiInputData.msg          = NULL;

        AudioCurationRouter_SendEvent(ui_input_anc_toggle_on_off, &uiInputData);
    }
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_ToggleWay(void)
{
    if (appPhyStateIsOutOfCase())
    {
        DEBUG_LOG("HeadsetTestAudioCuration_ToggleWay");
        ac_router_event_data_t uiInputData;

        uiInputData.msgLen       = 0;
        uiInputData.consumerFlag = ac_router_consumer_local_remote;
        uiInputData.delay        = PEER_ANC_UI_INPUT_DELAY_MS;
        uiInputData.msg          = NULL;

        AudioCurationRouter_SendEvent(ui_input_anc_toggle_way, &uiInputData);
    }
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_SetConcurrencyConfig(source_type_t active_source, uint8 mode, bool enable_toggle)
{
    DEBUG_LOG("HeadsetTestAudioCuration_SetConcurrencyConfig : active_source : %d , mode : %d , enable_toggle : %d",
                active_source, mode, enable_toggle);
    ac_router_event_data_t uiInputData;

    MESSAGE_MAKE(msg, ac_obj_msg_set_concurrency_t);
    msg->source_type = active_source;
    msg->toggle_config.req_obj = mode;
    msg->toggle_config.toggle_enable = enable_toggle;

    uiInputData.msgLen       = sizeof(ac_obj_msg_set_concurrency_t);
    uiInputData.consumerFlag = ac_router_consumer_local_remote;
    uiInputData.delay        = PEER_ANC_UI_INPUT_DELAY_MS;
    uiInputData.msg          = msg;

    AudioCurationRouter_SendEvent(ui_input_audio_curation_set_concurrency_config, &uiInputData);
}

UNITCODESECTION(KEEP)
uint8 HeadsetTestAudioCuration_GetCurrentMode(void)
{
    return appTestAudioCuration_GetCurrentMode();
}

UNITCODESECTION(KEEP)
audio_curation_provider_context_t HeadsetTestAudioCuration_GetContextState(void)
{
    DEBUG_LOG("HeadsetTestAudioCuration_GetContextState");

    ac_context_state_t current_context = AudioCuration_GetContext();
    return current_context.current_context;
}

UNITCODESECTION(KEEP)
uint8 HeadsetTestAudioCuration_GetNumModes(void)
{
    DEBUG_LOG("HeadsetTestAudioCuration_GetNumModes");

    /* Transitions are allowed only between use case specific objectives.
     * Hence based on number of modes, set_mode can be called.
     */
    return AudioCurationIntent_GetUseCaseObjectivesNumber();
}

UNITCODESECTION(KEEP)
bool HeadsetTestAudioCuration_EnableTuning(bool enable)
{
    DEBUG_LOG("HeadsetTestAudioCuration_EnableTuning");

    return AudioCurationObjectiveTuning_Enable(enable);
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_PsapVolumeUp(void)
{
    if (appPhyStateIsOutOfCase())
    {
        DEBUG_LOG("HeadsetTestAudioCuration_PsapVolumeUp");
        ac_router_event_data_t uiInputData;

        uiInputData.msgLen       = 0;
        uiInputData.consumerFlag = ac_router_consumer_local_remote;
        uiInputData.delay        = PEER_ANC_UI_INPUT_DELAY_MS;
        uiInputData.msg          = NULL;

        AudioCurationRouter_SendEvent(ui_input_anc_set_world_vol_up, &uiInputData);
    }
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_PsapVolumeDown(void)
{
    if (appPhyStateIsOutOfCase())
    {
        DEBUG_LOG("HeadsetTestAudioCuration_PsapVolumeDown");
        ac_router_event_data_t uiInputData;

        uiInputData.msgLen       = 0;
        uiInputData.consumerFlag = ac_router_consumer_local_remote;
        uiInputData.delay        = PEER_ANC_UI_INPUT_DELAY_MS;
        uiInputData.msg          = NULL;

        AudioCurationRouter_SendEvent(ui_input_anc_set_world_vol_down, &uiInputData);
    }
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_SetWorldVolume(uint8 obj, int16_t volume)

{
    if (appPhyStateIsOutOfCase())
    {
        DEBUG_LOG("HeadsetTestAudioCuration_SetWorldVolume");
        ac_router_event_data_t uiInputData;

        MESSAGE_MAKE(msg, ac_objective_set_world_volume_gain_t);
        msg->obj = obj;
        msg->volume_l = volume;
        msg->volume_r = volume;
        uiInputData.msgLen       = sizeof(ac_objective_set_world_volume_gain_t);
        uiInputData.consumerFlag = ac_router_consumer_local_remote;
        uiInputData.delay        = PEER_ANC_UI_INPUT_DELAY_MS;
        uiInputData.msg          = msg;

        AudioCurationRouter_SendEvent(ui_input_anc_set_world_volume_gain,
                                      &uiInputData);
    }
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_PsapHaFeatureEnable(uint32_t feature, bool enable)
{
    if (appPhyStateIsOutOfCase())
    {
        DEBUG_LOG("HeadsetTestAudioCuration_PsapHaFeatureEnable");
        ac_router_event_data_t uiInputData;
        MessageId msgId = enable ? ui_input_psap_ha_feature_enable:
                                   ui_input_psap_ha_feature_disable;

        MESSAGE_MAKE(msg, ac_objective_feature_t);
        msg->req_feature         = feature;
        uiInputData.msgLen       = sizeof(ac_objective_feature_t);
        uiInputData.consumerFlag = ac_router_consumer_local_remote;
        uiInputData.delay        = PEER_ANC_UI_INPUT_DELAY_MS;
        uiInputData.msg          = msg;

        AudioCurationRouter_SendEvent(msgId, &uiInputData);
    }
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_ToggleAncAdaptivity(void)
{
    if (appPhyStateIsOutOfCase())
    {
        DEBUG_LOG("HeadsetTestAudioCuration_ToggleAncAdaptivity");
        ac_router_event_data_t uiInputData;

        uiInputData.msgLen       = 0;
        uiInputData.consumerFlag = ac_router_consumer_local_remote;
        uiInputData.delay        = PEER_ANC_UI_INPUT_DELAY_MS;
        uiInputData.msg          = NULL;

        AudioCurationRouter_SendEvent(ui_input_anc_adaptivity_toggle_on_off, &uiInputData);
    }
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_SetAudiogram(uint8_t audiogram)
{
    if (appPhyStateIsOutOfCase())
    {
        DEBUG_LOG("HeadsetTestAudioCuration_SetAudiogram");
        ac_router_event_data_t uiInputData;

        MESSAGE_MAKE(msg, ac_objective_set_audiogram_t);
        msg->audiogram           = audiogram;
        uiInputData.msgLen       = sizeof(ac_objective_set_audiogram_t);
        uiInputData.consumerFlag = ac_router_consumer_local_remote;
        uiInputData.delay        = PEER_ANC_UI_INPUT_DELAY_MS;
        uiInputData.msg          = msg;

        AudioCurationRouter_SendEvent(ui_input_psap_set_audiogram,
                                      &uiInputData);
    }
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_SetVolume(uint8 obj, int16_t lvolume, int16_t rvolume)

{
    if (appPhyStateIsOutOfCase())
    {
        DEBUG_LOG("HeadsetTestAudioCuration_SetVolume");
        ac_router_event_data_t uiInputData;

        MESSAGE_MAKE(msg, ac_objective_set_world_volume_gain_t);
        msg->obj = obj;
        msg->volume_l = lvolume;
        msg->volume_r = rvolume;
        uiInputData.msgLen       = sizeof(ac_objective_set_world_volume_gain_t);
        uiInputData.consumerFlag = ac_router_consumer_local_remote;
        uiInputData.delay        = PEER_ANC_UI_INPUT_DELAY_MS;
        uiInputData.msg          = msg;

        AudioCurationRouter_SendEvent(ui_input_anc_set_world_volume_gain,
                                      &uiInputData);
    }
}

UNITCODESECTION(KEEP)
bool HeadsetTestAudioCuration_SetMonitorFeature(uint32 fid_mask)
{
    return AudioCurationMonitor_ConfigureFeature(fid_mask);
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_SetEqGain(uint8 obj, int16_t gain_level, bool peer_sync)
{
    if (appPhyStateIsOutOfCase())
    {
        DEBUG_LOG("HeadsetTestAudioCuration_SetOpenEqLevel");
        ac_router_event_data_t uiInputData;
        MESSAGE_MAKE(msg, ac_objective_set_open_eq_level_t);
        msg->obj = obj;
        msg->gain_level = gain_level;
        uiInputData.msgLen       = sizeof(ac_objective_set_open_eq_level_t);
        if(peer_sync )
            uiInputData.consumerFlag = ac_router_consumer_local_remote;
        else
            uiInputData.consumerFlag = ac_router_consumer_local;
        uiInputData.delay        = PEER_ANC_UI_INPUT_DELAY_MS;
        uiInputData.msg          = msg;
        AudioCurationRouter_SendEvent(ui_input_ambient_set_open_eq_level,
                                      &uiInputData);
    }
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_HearingTestStart(uint32_t channel, uint32_t frequency, int32_t loudness)
{
    DEBUG_LOG("HeadsetTestAudioCuration_HearingTestOpen");
    ac_router_event_data_t uiInputData;

    MESSAGE_MAKE(msg, hearing_test_start_msg_t);
    msg->channel      = channel;
    msg->freq         = frequency;
    msg->volume      = loudness;
    uiInputData.msgLen       = sizeof(hearing_test_start_msg_t);
    uiInputData.consumerFlag = get_MesageDirection(channel);
    uiInputData.delay        = 0;
    uiInputData.msg          = msg;

    AudioCurationRouter_SendEvent(ui_input_hearing_test_start,
                                  &uiInputData);
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_HearingTestStop(uint32_t channel)
{
    DEBUG_LOG("HeadsetTestAudioCuration_HearingTestClose");
    ac_router_event_data_t uiInputData;

    MESSAGE_MAKE(msg, hearing_test_stop_msg_t);
    msg->channel = channel;
    uiInputData.msgLen       = sizeof(hearing_test_stop_msg_t);
    uiInputData.consumerFlag = get_MesageDirection(channel);
    uiInputData.delay        = 0;
    uiInputData.msg          = msg;

    AudioCurationRouter_SendEvent(ui_input_hearing_test_stop,
                                  &uiInputData);
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_HearingTestStoreResult(uint32_t hearing_test, uint32_t channel, uint32_t audiogram_size, uint32_t audiogram_config[])
{
    DEBUG_LOG("HeadsetTestAudioCuration_HearingTestClose");
    ac_router_event_data_t uiInputData;
    hearing_test_store_audiogram_msg_t *audiogram = NULL;

    uiInputData.delay        = 0;
    uiInputData.msgLen       = sizeof(hearing_test_store_audiogram_msg_t) + audiogram_size;
    uiInputData.consumerFlag = get_MesageDirection(channel);
    uiInputData.msg          = PanicUnlessMalloc(uiInputData.msgLen);

    audiogram = (hearing_test_store_audiogram_msg_t*)uiInputData.msg;
    audiogram->hearing_test = hearing_test;
    audiogram->channel = get_MesageDirection(channel);
    audiogram->audiogram_size = audiogram_size;
    audiogram->audiogram_config = ((uint8 *)audiogram + (sizeof(hearing_test_store_audiogram_msg_t)));

    memcpy(audiogram->audiogram_config, audiogram_config, audiogram_size);

    AudioCurationRouter_SendEvent(ui_input_hearing_test_save_audiogram,
                                  &uiInputData);
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_HearingTestPlayTone(uint32_t channel, uint32_t frequency, int32_t loudness)
{
    DEBUG_LOG("HeadsetTestAudioCuration_HearingTestPlayTone");
    ac_router_event_data_t uiInputData;

    MESSAGE_MAKE(msg, hearing_test_start_msg_t);
    msg->channel      = channel;
    msg->freq         = frequency;
    msg->volume      = loudness;
    uiInputData.msgLen       = sizeof(hearing_test_start_msg_t);
    uiInputData.consumerFlag = get_MesageDirection(channel);
    uiInputData.delay        = 0;
    uiInputData.msg          = msg;

    AudioCurationRouter_SendEvent(ui_input_hearing_test_start,
                                  &uiInputData);
}

UNITCODESECTION(KEEP)
uint32_t HeadsetTestAudioCuration_GetModeChangeStatus(void)
{
    return AudioCurationUseCaseManager_GetModeChangeStatus();
}

UNITCODESECTION(KEEP)
void HeadsetTestAudioCuration_SetAdaptiveAudioTransparency(uint32_t anc_gain, uint32_t ambient_gain, uint32_t blend_time_ms)
{
    if (appPhyStateIsOutOfCase())
    {
        DEBUG_LOG("HeadsetTestAudioCuration_SetAdaptiveAudioGain");
        ac_router_event_data_t uiInputGainData, uiInputModeData;

        MESSAGE_MAKE(msg1, ac_obj_msg_set_adaptive_audio_gain_t);
        msg1->obj = 5;
        msg1->anc_gain = anc_gain;
        msg1->ambient_gain = ambient_gain;
        msg1->blend_duration = blend_time_ms;
        uiInputGainData.msgLen       = sizeof(ac_obj_msg_set_adaptive_audio_gain_t);
        uiInputGainData.consumerFlag = ac_router_consumer_local_remote;
        uiInputGainData.delay        = PEER_ANC_UI_INPUT_DELAY_MS;
        uiInputGainData.msg          = msg1;

        AudioCurationRouter_SendEvent(ui_input_anc_set_adaptive_audio_gain,
                                      &uiInputGainData);

        /* For ADK application there is no objective config to be passed along
         * with mode setting. All config sits in ACDB file.Hence msg->cfg is
         * set NULL
         */
        MESSAGE_MAKE(msg2, ac_set_objective_mode_t);
        msg2->req_obj = 5;
        msg2->cfg_length = 0;
        msg2->cfg = NULL;

        uiInputModeData.msgLen       = sizeof(ac_set_objective_mode_t) + msg2->cfg_length;
        uiInputModeData.consumerFlag = ac_router_consumer_local_remote;
        uiInputModeData.delay        = PEER_ANC_UI_INPUT_DELAY_MS;
        uiInputModeData.msg          = msg2;

        AudioCurationRouter_SendEvent(ui_input_audio_curation_set_mode, &uiInputModeData);
    }
}

void HeadsetTestAudioCuration_SetAdaptiveAudioPsap(uint32_t anc_gain, uint32_t  psap_gain, uint32 blend_time_ms)
{
    if (appPhyStateIsOutOfCase())
    {
        DEBUG_LOG("HeadsetTestAudioCuration_SetAdaptiveAudioGain");
        ac_router_event_data_t uiInputGainData, uiInputModeData;

        MESSAGE_MAKE(msg1, ac_obj_msg_set_adaptive_audio_gain_t);
        msg1->obj = 6;
        msg1->anc_gain = anc_gain;
        msg1->ambient_gain = psap_gain;
        msg1->blend_duration = blend_time_ms;
        uiInputGainData.msgLen       = sizeof(ac_obj_msg_set_adaptive_audio_gain_t);
        uiInputGainData.consumerFlag = ac_router_consumer_local_remote;
        uiInputGainData.delay        = PEER_ANC_UI_INPUT_DELAY_MS;
        uiInputGainData.msg          = msg1;

        AudioCurationRouter_SendEvent(ui_input_anc_set_adaptive_audio_gain,
                                      &uiInputGainData);

        /* For ADK application there is no objective config to be passed along
         * with mode setting. All config sits in ACDB file.Hence msg->cfg is
         * set NULL
         */
        MESSAGE_MAKE(msg2, ac_set_objective_mode_t);
        msg2->req_obj = 6;
        msg2->cfg_length = 0;
        msg2->cfg = NULL;

        uiInputModeData.msgLen       = sizeof(ac_set_objective_mode_t) + msg2->cfg_length;
        uiInputModeData.consumerFlag = ac_router_consumer_local_remote;
        uiInputModeData.delay        = PEER_ANC_UI_INPUT_DELAY_MS;
        uiInputModeData.msg          = msg2;

        AudioCurationRouter_SendEvent(ui_input_audio_curation_set_mode, &uiInputModeData);
    }
}


#endif /* INCLUDE_ANC_V3 */


